/*
 * File:   UserDelay.c
 * Author: Honrun
 */

#include "gd32f10x.h"
#include "stdint.h"
#include "DevicesDelay.h"


/*
 * Return:      void
 * Parameters:  void
 * Description: SysTick初始化
 */
void vSysTickDelayInit(void)
{
    SysTick->CTRL = SysTick_CTRL_TICKINT_Msk;                   /* TICKINT置1-单次触发、CLKSOURCE清零-SysTick时钟选择为系统时钟8分频 */
}

/*
 * Return:      void
 * Parameters:  Time: 延时时间
 * Description: 秒延时
 */
void vSysTickDelayS(float fTime)
{
    int32_t iTime = fTime;

    if(fTime < 0.001f)
        return;

    while((iTime--) > 0)
    {
        vSysTickDelayMs(1000);
    }

    fTime -= (int32_t)fTime;
    vSysTickDelayMs(fTime * 1000.0f);
}

/*
 * Return:      void
 * Parameters:  Time: 延时时间（范围：1~1864，系统时钟为72M时）
 * Description: 毫秒延时
 */
void vSysTickDelayMs(float fTime)
{
    if(fTime < 0.01f)
        return;

    SysTick->LOAD  = SystemCoreClock / 8000u * fTime - 1u;      /* Set the SysTick Counter Load */
    SysTick->VAL   = 0u;                                        /* Clear the SysTick Counter Value */
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;                   /* Enable SysTick Timer */

    while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0u);  /* 当VAL计数寄存器递减到0时，COUNTFLAG自动置1（读取后自动清零） */
}

/*
 * Return:      void
 * Parameters:  Time: 延时时间（范围：1~1864135，系统时钟为72M时）
 * Description: 微秒延时
 */
void vSysTickDelayUs(float fTime)
{
    if(fTime < 0.1f)
        return;

    SysTick->LOAD  = SystemCoreClock / 8000000u * fTime - 1u;   /* Set the SysTick Counter Load */
    SysTick->VAL   = 0u;                                        /* Clear the SysTick Counter Value */
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;                   /* Enable SysTick Timer */

    while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0u);  /* 当VAL计数寄存器递减到0时，COUNTFLAG自动置1（读取后自动清零） */
}

/*
 * Return:      void
 * Parameters:  void
 * Description: DWT初始化
 */
void vDWTDelayInit(void)
{
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CYCCNT = 0;
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}

/*
 * Return:      void
 * Parameters:  Time: 延时时间
 * Description: 秒延时
 */
void vDWTDelayS(float fTime)
{
    int32_t iTime = fTime;

    if(fTime < 0.001f)
        return;

    while((iTime--) > 0)
    {
        vDWTDelayMs(1000);
    }

    fTime -= (int32_t)fTime;
    vDWTDelayMs(fTime * 1000.0f);
}

/*
 * Return:      void
 * Parameters:  Time: 延时时间（范围：1~59652，系统时钟为72M时）
 * Description: 毫秒延时
 */
void vDWTDelayMs(float fTime)
{
    volatile uint32_t uiTimeStop = 0u, uiTimeStart = 0;

    if(fTime < 0.01f)
        return;

    uiTimeStart = DWT->CYCCNT;
    uiTimeStop  = (uint32_t)((SystemCoreClock / 1000u) * fTime) + uiTimeStart;

    if(uiTimeStop >= uiTimeStart)
        while((DWT->CYCCNT > uiTimeStart) && (DWT->CYCCNT < uiTimeStop));
    else
        while(!((DWT->CYCCNT > uiTimeStop) && (DWT->CYCCNT < uiTimeStart)));
}

/*
 * Return:      void
 * Parameters:  Time: 延时时间（范围：1~59652323，系统时钟为72M时）
 * Description: 微秒延时
 */
void vDWTDelayUs(float fTime)
{
    volatile uint32_t uiTimeStop = 0u, uiTimeStart = 0;

    if(fTime < 0.1f)
        return;

    uiTimeStart = DWT->CYCCNT;
    uiTimeStop  = (uint32_t)((SystemCoreClock / 1000000u) * fTime) + uiTimeStart;

    if(uiTimeStop >= uiTimeStart)
        while((DWT->CYCCNT > uiTimeStart) && (DWT->CYCCNT < uiTimeStop));
    else
        while(!((DWT->CYCCNT > uiTimeStop) && (DWT->CYCCNT < uiTimeStart)));
}
